package core.testcases;

import ibm.util.BrowserOps;

import java.io.IOException;
import java.util.ArrayList;

import authorization.firewall.Authorization;

import com.rational.test.ft.ObjectNotFoundException;
import com.rational.test.ft.object.interfaces.BrowserTestObject;
import com.rational.test.ft.object.interfaces.TestObject;
import com.rational.test.ft.script.RationalTestScript;

import core.PropertiesContainer;
import core.report.Reporting;

/**
 * Description : Functional Test Script
 * 
 * @author angel.tsvetkov
 */
public class TestProjectSuperHelper extends RationalTestScript {
	/**
	 * Flag which indicate whether the executed test script is part of test
	 * suite or not.
	 */
	private static boolean TEST_SUITE_FLAG = false;

	/**
	 * Flag which indicate whether the executed action is part of preconditions
	 * or from test step.
	 */
	protected static boolean preconditionReady = false;

	/**
	 * Represent name of the project
	 */
	public static String ProjectName = "";

	/**
	 * Represent the number of test step
	 */
	private static int testStepNumber = 0;

	/**
	 * Contains the boolean result from test case execution
	 */
	private static boolean testCaseResult = true;

	/**
	 * Array List from Test Cases
	 */
	private static ArrayList<TestCase> testCases = new ArrayList<TestCase>();

	/**
	 * Test Case object
	 */
	public static TestCase testCase = null;

	/**
	 * Test Step object
	 */
	public static TestStep testStep = null;

	/**
	 * Flag which indicate whether the report from test script execution is
	 * generated or not.
	 */
	private static boolean reportGenerated = false;

	// Initialize property container and log in through the firewall if the test
	// script will be executed on DEV box
	public void setUp(Object[] args) {
		try {
			if (args[0].equals("DEV")) {
				PropertiesContainer.setResourceName("core.Properties.DevBox");
			} else {
				if(args[0].equals("TEST"))
				{
					PropertiesContainer.setResourceName("core.Properties.TestBox");
				}
				else
				{
					PropertiesContainer.setResourceName("core.Properties.ProdBox");
				}
			}
			PropertiesContainer propContainer = PropertiesContainer.getInstance();
			if(propContainer.getPassFirewall())
			{
				Authorization.passMeThroughTheFirewall();
			}
		} catch (Exception ex) {
			setErrorComment("problem appear during seting up of the variables.", ex);
		}
	}

	/**
	 * Does any necessary cleanup.
	 * 
	 * @see #setUp(Object[])
	 */
	public void tearDown() { /*
							 * by default this is the tear down for ALL test
							 * cases. it is probably better if you have a test
							 * helper that extends this class in each test
							 * bucket before modifying this method
							 */
	}
	
	public enum Browsers
	{
		Firefox,
		IE
	};
	
	public static void cloaseBrowser()
	{
		cloaseBrowser(Browsers.Firefox);
	}
	
    public static void cloaseBrowser(Browsers browser)
    {
    	if(browser != null)
    	{
    		switch (browser) 
    		{
			case Firefox:
				{
					try {
						Process action = Runtime.getRuntime().exec("cmd /C taskkill /IM firefox.exe");
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}break;
				
				
			case IE:
				try {
					Process action = Runtime.getRuntime().exec("cmd /C taskkill /IM iexplore.exe");
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				break;

			}
    		
    		TimeWait(2);
    	}
    }

	/**
	 * Log message to the script log file. This method colors the message in
	 * blue if the message is indicating success, otherwise it colors the
	 * message in red
	 * 
	 * @param String
	 *            logMsg - message to log
	 * 
	 * @param boolean result true or false depending on the message status -
	 *        error or success
	 */
	public static void logTestResult(String logMsg, boolean result) {
		if (!result) {
			RationalTestScript.logTestResult("<font color\"red\">" + logMsg
					+ " failed</font>", false);
		} else {
			RationalTestScript.logTestResult("<font color\"blue\">" + logMsg
					+ " successful</font>", true);
		}
	}

	/**
	 * Initialize the basic variables which are used during the test execution.
	 * Set the test case meta data.
	 * 
	 * @param String
	 *            testCaseID - Represent the test case ID
	 * @param String
	 *            testCaseDescription - Represent the test case description
	 * @param String
	 *            coveredRequirement - Represent the IDs of the covered
	 *            requirements, if there are any.
	 * @param String
	 *            createdBy - Represent the author of the test script
	 * @param String
	 *            coveredDefect - Represent the IDs of the covered defects if
	 *            there are any
	 * @param String
	 *            testCaseComment - Set any additional comments to the test
	 *            script.
	 * 
	 *            Note: Covered defects and Additional comments can be omit.
	 *            Performed By property is entered dynamically from the computer
	 *            name.
	 */
	public void beginTestCase(String testCaseID,
			String testCaseDescription, String coveredRequirement,
			String createdBy, String coveredDefect, String testCaseComment) {

		// Down the flag for report generation
		reportGenerated = false;

		// Initialize Test Case and Test Step global objects
		testCase = new TestCase();
		testStep = new TestStep();

		// Get Computer name and set it as performed by property.
		String performedBy = System.getProperty("user.name");

		// Set the test step initial number
		testStepNumber = 1;

		// Assume that the test case result is OK
		testCaseResult = true;

		// Initialize containers for Test Case Meta data and Additional
		// Information
		String testCaseMetaData = null;
		String metaDataAddInfo = null;

		// Apply Test Case meta data to the already initialized objects
		testCase.setTestCaseID(testCaseID);
		testCase.setTestCaseDescription(testCaseDescription);
		testCase.setCoveredRequirement(coveredRequirement);
		testCase.setCreatedBy(createdBy);
		testCase.setPerformedBy(performedBy);
		testCase.setCoveredDefect(coveredDefect);
		testCase.setTestCaseComment(testCaseComment);

		// Set Test Case Meta Data
		testCaseMetaData = testCaseID + " : " + testCaseDescription;

		// Set Test Case Additional Information
		metaDataAddInfo = " \n Requirement(s): " + coveredRequirement;
		metaDataAddInfo += "\n Created By: " + createdBy;
		metaDataAddInfo += "\n Performed By: " + performedBy;

		// Check whether there are any covered defects. If there isn't, covered
		// defects section in the report will be empty.
		if (coveredDefect != "" && coveredDefect != null) {
			metaDataAddInfo += "\n Test Case Covered Defect(s): "
					+ coveredDefect;
		}

		// Check whether there are any additional comments. If there isn't,
		// comments section in the report will be empty.
		if (testCaseComment != "" && testCaseComment != null) {
			metaDataAddInfo += "\n Comment: " + testCaseComment;
		}

		// Set the meta data in the RFT report, it is not used any more, but the
		// code is not retired because of future changes.
		RationalTestScript.logTestResult(testCaseMetaData, true,
				metaDataAddInfo);
	}

	/**
	 * Set the step result
	 * 
	 * @param boolean result - boolean real test step result
	 * @param String
	 *            expectedResult - description of expected result
	 * @param String
	 *            realResult - description of the real result.
	 */
	public void setStepResult(boolean result, String expectedResult,
			String realResult) {

		// Check whether the step result is NOK. If it is, the test case result
		// is changed to NOK and never changed.
		if (!result) {
			testCaseResult = false;
		}

		// Set step number, expected result description and boolean
		// representation of the result in the objects which contains the report
		// info
		testStep.setNumber(testStepNumber);
		testStep.setExpectedResult("Test" + expectedResult);
		testStep.setResult(result);

		// Put the test step in Test Case Array List and clear the test step
		// object
		testCase.addTestStep(new TestStep(testStep));
		testStep.clear();

		// Report the step result
		reportStepResult(result, expectedResult, realResult);

		// Increment test step number
		testStepNumber++;
	}

	/**
	 * Set the step result
	 * 
	 * @param boolean result - boolean real test step result
	 * @param String
	 *            expectedResult - description of expected result
	 */
	public void setStepResult(boolean result, String expectedResult) {

		// Check whether the step result is NOK. If it is, the test case result
		// is changed to NOK and never changed.
		if (!result) {
			testCaseResult = false;
		}

		// Set step number, expected result description and boolean
		// representation of the result in the objects which contains the report
		// info
		testStep.setNumber(testStepNumber);
		testStep.setExpectedResult("Test Step " + testStepNumber + ": "
				+ expectedResult);
		testStep.setResult(result);

		// Put the test step in Test Case Array List and clear the test step
		// object
		testCase.addTestStep(new TestStep(testStep));
		testStep.clear();

		// Report the step result
		reportStepResult(result, expectedResult);

		// Increment test step number
		testStepNumber++;
	}

	/**
	 * Log the expected and real result in the RFT report
	 * 
	 * @param boolean result - boolean real test step result
	 * @param String
	 *            expectedResult - description of expected result
	 * @param String
	 *            realResult - description of the real result.
	 */
	private void reportStepResult(boolean result, String expectedResult,
			String realResult) {
		logTestResult("Test Step " + testStepNumber + " - " + expectedResult
				+ ":", result, "Real Result: " + realResult);
	}

	/**
	 * Log the expected in the RFT report
	 * 
	 * @param boolean result - boolean real test step result
	 * @param String
	 *            expectedResult - description of expected result
	 */
	private void reportStepResult(boolean result, String expectedResult) {
		logTestResult("Test Step " + testStepNumber + " - " + expectedResult
				+ ":", result);
	}

	/**
	 * Log comment in RFT report and in the object which contains report data as
	 * well. Note: Print the comment in the console as well.
	 * 
	 * @param String
	 *            Comment - comment
	 */
	public static void setComment(String Comment) {
		if(testStep != null)
		{
			testStep.actions.add(Comment);
		}
		System.out.println(Comment);
		logInfo(Comment);
	}

	/**
	 * Log error message in RFT report and in the object which contains report
	 * data as well
	 * 
	 * @param String
	 *            Comment - error message
	 */
	public static void setErrorComment(String Comment) {
		if(testStep != null)
		{
			testStep.actions.add(Comment);
		}
		System.err.println(Comment);
		logInfo(Comment, getRootTestObject().getScreenSnapshot());
	}
	
	public static void setErrorComment(String Comment, Exception ex) {
		setErrorComment(Comment);
		ex.printStackTrace();
	}

	/**
	 * Log the task result
	 * 
	 * @param boolean result - boolean real test step result
	 * @param String
	 *            title - Title of the task
	 * @param String
	 *            additionalInformation - Additional actions which are performed
	 *            during the task execution
	 */
	public static void setTaskResult(String title, boolean result,
			String additionalInformation) {
		setTaskResult(title, result, additionalInformation, true);
	}

	/**
	 * Log the task result
	 * 
	 * @param boolean result - boolean real test step result
	 * @param String
	 *            title - Title of the task
	 * @param String
	 *            additionalInformation - Additional actions which are performed
	 *            during the task execution
	 * 
	 * @param boolean writeInTheReport - flag which indicate whether the task
	 *        will be set in the report or not.
	 */
	public static void setTaskResult(String title, boolean result,
			String additionalInformation, boolean writeInTheReport) {
		String taskSteps = null;

		try {
			// That control is done to determine is there a failed task action.
			// If there is any, that will be the last reported action. By that
			// control is determined which is the last action. That is needed
			// for future report formating (change the color of the failed
			// action)
			if (!result) {
				taskSteps = additionalInformation.substring(0,
						additionalInformation.lastIndexOf("\n"));
				taskSteps += additionalInformation
						.substring(additionalInformation.lastIndexOf("\n"));
			} else {
				// If everything is OK all the actions are reported in the same
				// way.
				taskSteps = additionalInformation;
			}
		} catch (IndexOutOfBoundsException ex) {
			// If that exception is thrown, that means that there is only one
			// action in the task.
			taskSteps = additionalInformation;
		}

		if (writeInTheReport) {

			// Check whether that is a task called from test case precondition
			// or from separate test step.
			if (!preconditionReady) {
				if(testCase != null)
				{
					testCase.preconditions.add(taskSteps);
				}
			} else {
				if(testStep != null)
				{
					testStep.actions.add(taskSteps);
				}
			}
		}

		// Log the result in RFT report
		logTestResult(title, result, taskSteps);
	}

	/**
	 * Fill the report data gathering objects with info
	 * 
	 * @param String
	 *            Result - expected result
	 * @param String
	 *            project - Project name
	 */
	public void reportTestCaseResult(String Result, String project) {
		Reporting reportFile = new Reporting();

		// Fill info
		testCase.setResult(testCaseResult);
		testCase.setBriefDescription(Result);

		// Determine report url
		testCase.setTestCaseURL(reportFile.generateReport(testCase,
				project));

		// Add test case object in the Array List of Test Cases
		testCases.add(new TestCase(testCase));

		// Clear test case object
		testCase.clear();

		// Up the flag which indicate that the report is generated
		reportGenerated = true;

		// Log in the RFT report
		logTestResult(Result, testCaseResult);

		// Set the initial step number
		testStepNumber = 1;

		// Show the generated report
		showReport();
	}

	/**
	 * Show the generated report
	 */
	private void showReport() {
		if (reportGenerated && !TEST_SUITE_FLAG) {
			for (int testCaseNumber = 0; testCaseNumber < testCases.size(); testCaseNumber++) {
				if (!testCases.get(testCaseNumber).getTestCaseURL().isEmpty()) {
					startBrowser(testCases.get(testCaseNumber).getTestCaseURL());
					TimeWait(1);
				}
			}

			// Clear the Array List of test cases
			testCases.clear();
		}
	}

	/**
	 * Indicate that suite of test cases will be executed. That is important for
	 * report generation.
	 */
	public void beginTestSuite() {
		TEST_SUITE_FLAG = true;
	}

	/**
	 * Indicate that execution of test suite is finished. That is important for
	 * report generation.
	 */
	public void finishTestSuite() {
		TEST_SUITE_FLAG = false;
		showReport();
	}

	/**
	 * Wait for a specified seconds, there is a option to report that wait in
	 * the report
	 */
	public static void TimeWait(int timeInSeconds, boolean setInReport) {
		if (setInReport) {
			testStep.actions.add("Time to wait " + timeInSeconds + " seconds.");
			logInfo("Time to wait " + timeInSeconds + " seconds.");
		}
		sleep(timeInSeconds);
	}

	/**
	 * Wait for a specified seconds. That is not reported.
	 */
	public static  void TimeWait(int timeInSeconds) {
		TimeWait(timeInSeconds, false);
	}
}
